<template>
  <TableLayout class="full-page relative" v-model:page="page_num" v-model:size="size" :total="total"
    @table-change="getTableData" :no-page="noPage">
    <template #header>
      <div class="flex items-center justify-between">
        <TopFilter :model="params" :filters="filters" @change="getTableData()" />
        <div class="flex items-center">
          <slot name="top-right"></slot>
          <el-button v-if="createForm" type="primary" @click="onAdd()">添加{{ title }}</el-button>
        </div>
      </div>
    </template>
    <template #table>
      <el-table :data="tableData" height="100%" border v-loading="loading" @selection-change="onSelection">
        <el-table-column v-if="selectable" type="selection"></el-table-column>
        <el-table-column v-for="col in columns" :key="col.prop" :label="col.label" :prop="col.prop"
          :min-width="col.minWidth">
          <template #default="{ row }">
            <template v-if="col.render">
              <component :is="col.render(row)"></component>
            </template>
            <template v-else>{{ row[col.prop] }}</template>
          </template>
        </el-table-column>
        <el-table-column v-if="!hideHandle" label="操作" fixed="right" :width="fixedColWidth">
          <template #default="{ row }">
            <el-button v-if="canEdit(row)" type="primary" link @click="onEdit(row)">{{
              editText
              }}</el-button>
            <slot name="handler" v-bind="{ row, callback: getTableData }"></slot>
            <el-button v-if="canDelete(row)" type="danger" link @click="onDelete(row)">删除</el-button>
          </template>
        </el-table-column>
        <template #empty>
          <EmptyImg />
        </template>
      </el-table>
    </template>

    <template #dialog>
      <el-dialog v-model="visible" :title="(info ? editText : '添加') + title" :width="dialogWidth" destroy-on-close>
        <ConfigForm :info="info" :server="server" :rawKey="rawKey" :configs="info ? editForm : createForm"
          :beforeSubmit="beforeSubmit" @success="getTableData" @close="visible = false"></ConfigForm>
      </el-dialog>
      <slot name="dialog"></slot>
    </template>
  </TableLayout>
</template>

<script setup>
import TableLayout from '@/components/TableLayout.vue'
import TopFilter from './TopFilter.vue'
import ConfigForm from './ConfigForm.vue'
import { useFilters, useTable } from '@/hooks'
import { ElMessage, ElMessageBox } from 'element-plus'
import { ref } from 'vue'

const props = defineProps({
  title: String,
  rawKey: String,
  server: {
    type: Object,
    required: true,
  },
  filters: {
    type: Array,
    default: () => [],
  },
  noPage: Boolean,
  columns: {
    type: Array,
    required: true,
  },

  createForm: [Array, String],

  editForm: [Array, String],
  editText: {
    type: String,
    default: '修改',
  },
  editable: Function,

  beforeSubmit: Function,
  deleteable: [Boolean, Function],
  dialogWidth: {
    type: String,
    default: '600px',
  },
  fixedColWidth: String,
  hideHandle: Boolean,
  afterGetData: Function,
  selectable: Boolean,
})
const emit = defineEmits(['create', 'edit', 'selection'])

const { params, getParams, reset } = useFilters(props.filters)

const { page_num, size, total, tableData, getData, loading } = useTable(
  props.server.get,
  props.noPage,
)

const getTableData = (keepPage) => {
  if (!keepPage) page_num.value = 1
  getData(getParams()).then(() => {
    if (props.afterGetData) {
      tableData.value = props.afterGetData(tableData.value)
    }
  })
}
getTableData()
const resetParams = () => {
  reset()
  getTableData()
}

defineExpose({
  getTableData,
  getParams,
  resetParams,
})

const canEdit = (row) => {
  return props.editable ? props.editable(row) : !!props.editForm
}
const canDelete = (row) => {
  if (typeof props.deleteable === 'function') {
    return props.deleteable(row)
  } else {
    return props.deleteable
  }
}

const visible = ref(false)
const info = ref(null)
const onAdd = () => {
  if (props.createForm === 'custom') {
    emit('create')
    return
  }
  info.value = null
  visible.value = true
}
const onEdit = (row) => {
  if (props.editForm === 'custom') {
    emit('edit', row)
    return
  }
  info.value = row
  visible.value = true
}

const onDelete = (row) => {
  ElMessageBox.confirm('此操作将永久删除该数据, 是否继续?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(() => {
    props.server
      .delete({
        [props.rawKey]: row[props.rawKey] || row.id,
      })
      .then(() => {
        getTableData()
        ElMessage.success('删除成功')
      })
  })
}

const onSelection = (selection) => {
  emit('selection', selection)
}
</script>
